package com.hotec.PROJECT_NAME.component.basic;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.gemcap.framework.data.auth.GcAuthentication;
import com.gemcap.framework.data.dao.mapper.enhance.EnhanceBaseDataMapper;
import com.gemcap.framework.data.entity.SoftDelEntity;
import com.gemcap.framework.data.entity.TreeAble;
import com.gemcap.framework.data.serivce.BaseDataServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Sets;
import com.hotec.PROJECT_NAME.component.exception.exc.BizException;
import com.hotec.PROJECT_NAME.modules.sys.entity.SysAccount;
import com.hotec.PROJECT_NAME.modules.sys.entity.SysAttachment;
import com.hotec.PROJECT_NAME.modules.sys.service.SysAttachmentService;
import com.hotec.PROJECT_NAME.utils.UtilsAccount;
import com.hotec.PROJECT_NAME.utils.UtilsLog;
import com.hotec.PROJECT_NAME.utils.UtilsSpring;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.ibatis.exceptions.TooManyResultsException;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import tk.mybatis.mapper.entity.Example;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

/**
 * @author 黑山老妖
 * @date 2018/9/27
 */
@Transactional(rollbackFor = Exception.class)

public class BaseService<E extends BaseEntity, D extends EnhanceBaseDataMapper<E, String>> extends BaseDataServiceImpl<E, D> implements GcAuthentication {


    @Autowired
    protected BCryptPasswordEncoder bCryptPasswordEncoder;


    /**
     * 获取当前登录账号的username
     *
     * @param strict
     * @return
     */
    @Override
    public String getCurrentAccountId(Boolean... strict) {
        return UtilsAccount.getCurrentAccountId(strict);
    }

    public String getCurrentAccountShopId(Boolean... strict) {
        SysAccount currentAccount = this.getCurrentAccount(true);

        String shopId = currentAccount.getShopId();

        if(StrUtil.isBlank(shopId)){
            Assert.isTrue(ArrayUtil.isEmpty(strict) || !strict[0], "未找到您的店铺");
        }

        return shopId;
    }

    public SysAccount getCurrentAccount(Boolean... strict) {
        return UtilsAccount.getCurrentAccount(strict);
    }

    @Override
    protected void checkChildrenExist(E entity, boolean isSoftDelEntity) {
        if (entity instanceof TreeAble) {
            E param = null;
            try {
                param = this.getEntityClazz().newInstance();
            } catch (Exception e) {
                UtilsLog.log(this.getClass(), e);

                throw new BizException("操作失败，请联系管理员");
            }
            ((TreeAble) param).setParentId(entity.getId());
            if (isSoftDelEntity) {
                ((SoftDelEntity) param).setDelFlag("0");
            }
            List<E> child = this.mapper.select(param);
            if (org.apache.commons.collections.CollectionUtils.isNotEmpty(child)) {
                throw new com.gemcap.framework.common.exception.BizException("要删除的对象包含子类，请先删除子类！");
            }

        }
    }

    /**
     * 根据对象查询单条数据
     *
     * @param t
     * @param strict
     * @return
     */
    public E getOne(E t, boolean... strict) {
        try {
            E result = this.mapper.selectOne(t);

            if (ArrayUtils.isNotEmpty(strict) && strict[0]) {
                Assert.notNull(result, "查询对象为空！");
            }

            return result;
        } catch (MyBatisSystemException e) {
            UtilsLog.log(this.getClass(), e);

            if (e.getRootCause() instanceof TooManyResultsException) {
                throw new BizException("返回的数据太多，请检查查询条件！");
            } else {
                throw new BizException("查询数据库失败");
            }
        }
    }

    /**
     * 不分页查询
     *
     * @param orderBy
     * @param t
     * @return
     */
    public List<E> query(String orderBy, E t) {
        skipEmptyString(t);
        PageHelper.orderBy(orderBy);
        //默认查询未删除的
        t.setDelFlag("0");
        List<E> list = this.mapper.select(t);
        return list;
    }

    /**
     * 按条件查询所有
     *
     * @return
     */
    public List<E> queryAll(E entity) {
        entity.setDelFlag("0");
        return this.mapper.select(entity);
    }

    public List<E> queryAll(E entity, String orderBy) {
        entity.setDelFlag("0");
        PageHelper.orderBy(orderBy);
        return this.mapper.select(entity);
    }

    /**
     * 提出空字符串的内容，转换成成null
     *
     * @param entity
     */
    private void skipEmptyString(E entity) {
        final BeanWrapper src = new BeanWrapperImpl(entity);
        java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();
        for (java.beans.PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue instanceof String && org.springframework.util.StringUtils.isEmpty(String.valueOf(srcValue))) {
                src.setPropertyValue(pd.getName(), null);
            }
        }
    }

    /**
     * example 分页查询
     *
     * @param pageNo
     * @param pageSize
     * @param orderBy
     * @param example
     * @return
     */
    public PageInfo<E> queryByExample(Integer pageNo, Integer pageSize, String orderBy, Example example) {
        PageHelper.startPage(pageNo, pageSize).setOrderBy(orderBy);
        Example ext = new Example(this.getEntityClazz());
        Example.Criteria criteria = ext.createCriteria();
        criteria.andEqualTo("delFlag", "0");
        example.and(criteria);
        return new PageInfo(this.mapper.selectByExample(example));
    }

    /**
     * example 不分页查询
     *
     * @param orderBy
     * @param example
     * @return
     */
    public List<E> queryByExample(String orderBy, Example example) {
        PageHelper.orderBy(orderBy);
        Example ext = new Example(this.getEntityClazz());
        Example.Criteria criteria = ext.createCriteria();
        criteria.andEqualTo("delFlag", "0");
        example.and(criteria);
        return this.mapper.selectByExample(example);
    }

    /**
     * 物理删除,逗号隔开
     *
     * @param ids
     */
    public void dropById(String ids) {
        org.springframework.util.Assert.hasText(ids, "要删除的对象不能为空！");
        List<String> idList = Arrays.asList(ids.split(","));
        idList.stream().forEach(item -> {
            Class<E> t = this.getEntityClazz();
            try {
                E entity = t.newInstance();
                checkChildrenExist((E) entity.setId(item), false);
                this.mapper.deleteByPrimaryKey(item);
            } catch (InstantiationException | IllegalAccessException e) {
                UtilsLog.log(this.getClass(), e);

                throw new com.gemcap.framework.common.exception.BizException("删除失败！");
            }
        });
    }

    /**
     * 查询所有
     *
     * @return
     */
    public List<E> queryAll() {
        Example example = new Example(this.getEntityClazz());
        example.createCriteria().andEqualTo("delFlag", "0");
        return this.mapper.selectByExample(example);
    }

    /**
     * 分页查询
     *
     * @param pageNo
     * @param pageSize
     * @param orderBy
     * @param t
     * @return
     */
    public PageInfo<E> query(Integer pageNo, Integer pageSize, String orderBy, E t) {
        skipEmptyString(t);
        PageHelper.startPage(pageNo, pageSize).setOrderBy(orderBy);
        //默认查询未删除的
        t.setDelFlag("0");
        List<E> list = this.mapper.select(t);
        return new PageInfo(list);
    }

    @Override
    public void handleAttachmentEntity(E entity) {
        if (entity instanceof AttachmentAble) {
            AttachmentAble tmp = (AttachmentAble) entity;
            List<SysAttachment> attachments = tmp.getSysAttachments();
            if (CollectionUtils.isEmpty(attachments)) {
                return;
            }
            SysAttachmentService sysAttachmentService = UtilsSpring.getBean(SysAttachmentService.class);
            sysAttachmentService.saveAttachments(attachments, entity.getId());
        }

    }

    @Override
    public Set<String> getPropIncludeByPage() {
        return Sets.newHashSet();
//        return Sets.newHashSet("createUser","updateUser");
    }


}

